package com.northpool.operator.platform.datacenter;

import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.http.Method;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.northpool.operator.annotation.InputParam;
import com.northpool.operator.annotation.InputParams;
import com.northpool.operator.annotation.OperatorInfo;
import com.northpool.operator.common.database.DatabaseUtils;
import com.northpool.operator.common.jianmu.param.DataSourceBean;
import com.northpool.operator.param.ParamTool;
import com.northpool.operator.param.Parameter;
import com.northpool.operator.utils.StpOperatorHelper;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.nodes.Tag;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;

@OperatorInfo(
        ref = "dataCenterSyncDataSourceOperator",
        version = "1.0.0",
        name = "数据中心数据源信息批量同步",
        description = "同步平台下所有指定角色下的用户数据源连接信息"
)
public class DataCenterSyncDataSourceOperator extends StpOperatorHelper {
    static final String ASSOCIATION_TYPE = "platform";

    private static final DumperOptions options = new DumperOptions();
    private static final Yaml yaml;

    static {
        options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); // 使用块风格
        options.setPrettyFlow(true); // 使输出更易读
        options.setIndentWithIndicator(true);
        options.setIndicatorIndent(2);
        options.setIndent(2); // 设置缩进为2个空格
        options.setAllowUnicode(true); // 允许Unicode字符

        yaml = new Yaml(options);
    }


    @InputParams({
            @InputParam(ref = "serverUrl", name = "平台地址", desc = "http://spatial.mnr.gov.cn", value = "", required = true, testValue = ""),
            @InputParam(ref = "token", name = "用户TOKEN", desc = "用户TOKEN由平台登录用户接口获取", required = true),
            @InputParam(ref = "postIds", name = "角色ID", desc = "多个角色ID逗号隔开", required = true),
            @InputParam(ref = "platform", name = "关联平台", desc = "填充外部参数的来源，默认来源于工具中心", value = "tool-center")
    })
    public DataCenterSyncDataSourceOperator() {
        super();
    }

    public static void main(String[] args) throws Exception {
        ParamTool paramTool = ParamTool.aBuilder()
                .add("serverUrl", Parameter.Type.STRING.newParameter("http://192.168.164.45:8021"))
                .add("token", Parameter.Type.STRING.newParameter("d558b301c23a6f5192dea85db31bba39"))
                .add("postIds", Parameter.Type.STRING.newParameter("ff8081819279340e01927a51e7780003"))
                .add("platform", Parameter.Type.STRING.newParameter("tool-center"))
                .build();
        DataCenterSyncDataSourceOperator operator = new DataCenterSyncDataSourceOperator();
        operator.execute(paramTool);
    }

    @Override
    public void execute(ParamTool params) throws Exception {
        String serverUrl = params.getStr("serverUrl");
        String token = params.getStr("token");
        String postIds = params.getStr("postIds");
        String platform = params.getStr("platform");

        // 获取角色下的用户
        // hutool 发送 x-www-form-urlencoded 格式的请求体
        String[] postIdArr = postIds.split(",");
        for (String id : postIdArr) {
            try(HttpResponse execute = HttpUtil.createPost(serverUrl + "/datahub/usercenter/post/user_list").form(MapUtil.ofEntries(
                    MapUtil.entry("postId", id),
                    MapUtil.entry("page", "1"),
                    MapUtil.entry("start", "0"),
                    MapUtil.entry("limit", "1000") // 先只取1000，已满足现场需求
            )).execute()) {
                if (!execute.isOk()) {
                    throw new RuntimeException("获取用户列表失败：" + execute.body());
                }
                String body = execute.body();
                JSONObject bodyObj = JSONObject.parseObject(body);
                JSONArray dataSource = bodyObj.getJSONArray("dataSource");
                if (Objects.isNull(dataSource)) {
                    continue;
                }
                for (Object o : dataSource) {
                    JSONObject user = (JSONObject) o;
                    if (Objects.isNull(user)) continue;
                    String userId = user.getString("id");
                    String username = user.getString("username");
                    String trueName = user.getString("true_name");
                    this.log("处理用户: {}, 真实名: {}", username, trueName);
                    this.dealItem(serverUrl, token, platform, userId);
                }
            }
        }
    }

    private void dealItem(String serverUrl, String token,String platform, String userId) {
        String url = StrUtil.format("{}/datahub/system/vcatalogservicedatatype/treeloadusertable?node=shujuziyuanmuluROOT&child=true&userId={}", serverUrl, userId);
        try (
                HttpResponse execute = HttpUtil.createRequest(Method.POST, url)
                        //.header("token", token) 使用userId获取，忽略token
                        .setReadTimeout(5000)
                        .timeout(5000)
                        .execute();
        ) {
            if (!execute.isOk()) {
                throw new RuntimeException("数据中心结果异常, 状态码: " + execute.getStatus() + ",响应结果: " + execute.body());

            }
            String body = execute.body();
            if (StrUtil.isBlank(body)) {
                throw new RuntimeException("返回目录为空");
            }
            Map<String, DataSourceBean> dbMap = new LinkedHashMap<>();
            JSONArray array = JSONArray.parseArray(body);
            this.deepBuildDbMap(array, dbMap);

            // 获取所有数据源参数
            String paramGetUrl = StrUtil.format("{}/stp-jianmu-api/view/external_parameters?type=DB&associationId={}&associationType={}&associationPlatform={}",
                    serverUrl, userId, ASSOCIATION_TYPE, platform);

            HttpResponse paramGetExecute = HttpUtil.createRequest(Method.GET, paramGetUrl)
                    .header("token", token).execute();
            if (!paramGetExecute.isOk()) {
                throw new RuntimeException("获取当前用户的数据源参数异常: " + paramGetExecute.body());
            }
            JSONArray paramArray = JSONArray.parseArray(paramGetExecute.body());
            Map<String, String> oldParamMap = new HashMap<>();
            Map<String, String> idRefMap = new HashMap<>();
            for (Object obj : paramArray) {
                JSONObject paramObj = (JSONObject) obj;
                oldParamMap.put(paramObj.getString("ref"), paramObj.getString("value"));
                oldParamMap.put(paramObj.getString("ref"), paramObj.getString("id"));
            }

            for (DataSourceBean dataSource : dbMap.values()) {
                Object jsonObject = JSONObject.toJSON(dataSource);
                String ymlValue = yaml.dumpAs(jsonObject, Tag.MAP, DumperOptions.FlowStyle.BLOCK);
                // 注册或更新全局参数到工具中
                // {"ref":"test","name":"test","type":"STRING","value":"test","label":"默认"}
                // 更新的话是PUT请求
                Method method = Method.POST;
                JSONObject requestBody = new JSONObject();
                requestBody.put("ref", dataSource.getRef());
                requestBody.put("name", dataSource.getName());
                requestBody.put("type", "DB");
                requestBody.put("label", "数据中心");
                requestBody.put("value", ymlValue);
                requestBody.put("associationId", userId);
                requestBody.put("associationType", ASSOCIATION_TYPE);
                requestBody.put("associationPlatform", platform);
                if (oldParamMap.containsKey(dataSource.getRef())) {
                    method = Method.PUT;
                    requestBody.put("id", oldParamMap.get(dataSource.getRef()));
                    requestBody.remove("ref");
                }
                String paramUrl = serverUrl + "/stp-jianmu-api/external_parameters";
                HttpResponse paramExecute = HttpUtil.createRequest(method, paramUrl)
                        .body(requestBody.toJSONString())
                        .header("token", token).execute();
                if (!paramExecute.isOk()) {
                    throw new RuntimeException("工具中心注册数据源参数失败：" + paramExecute.body());
                }
            }
        } catch (Exception e) {
            this.error(ExceptionUtil.getMessage(e));
            throw new RuntimeException("数据中心结果处理异常: " + e.getMessage());
        }
    }

    private void deepBuildDbMap(JSONArray array, Map<String, DataSourceBean> dbMap) {
        for (Object object : array) {
            JSONObject jsonObj = (JSONObject) object;
            JSONObject attributes = jsonObj.getJSONObject("attributes");
            if ("123".equals(attributes.getString("dataType"))) {
                String sourceId = attributes.getString("sourceId");
                DataSourceBean ds = dbMap.get(sourceId);
                if (!dbMap.containsKey(sourceId)) {
                    // 从nacos中获取数据源名称，如果nacos里没有就不记录该条信息
                    String dataSourceName = DatabaseUtils.getDataSourceName(sourceId);
                    if (dataSourceName == null) {
                        this.error("Nacos中不存在数据源ID: {}, 请联系数据中心运维人员同步, 当前同步任务忽略该数据源", sourceId);
                        continue;
                    }

                    ds = new DataSourceBean();
                    ds.setRef(sourceId);
                    ds.setDescription(dataSourceName);
                    ds.setName(dataSourceName);
                    ds.setDatasets(new ArrayList<>());
                    dbMap.put(sourceId, ds);
                }

                DataSourceBean.DatasetBean dataset = new DataSourceBean.DatasetBean();
                dataset.setRef(attributes.getString("gridName"));
                dataset.setName(attributes.getString("name"));
                ds.getDatasets().add(dataset);
            } else if ("-99".equals(attributes.getString("dataType"))) {
                JSONArray children = jsonObj.getJSONArray("children");
                this.deepBuildDbMap(children, dbMap);
            }
        }
    }
}
